/*
 * Copyright (C) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef OHOS_WIFI_HID2D_CFG_H
#define OHOS_WIFI_HID2D_CFG_H

#include <vector>
#include <string>
#include "wifi_common_util.h"
#include "wifi_hid2d_msg.h"

namespace OHOS {
namespace Wifi {
enum class DeviceType {
    /** phone device type id */
    DEVICE_TYPE_PHONE_ID = 0,
    /** pad device type id */
    DEVICE_TYPE_PAD_ID = 1,
    /** pad tv type id */
    DEVICE_TYPE_TV_ID = 2,
    /** pad pc type id */
    DEVICE_TYPE_PC_ID = 3,
    /** pad display type id */
    DEVICE_TYPE_DISPLAY_ID = 4,
    /** pad car type id */
    DEVICE_TYPE_CAR_ID = 5,
};

enum class DeviceClass {
    Default,
    TABLET,
    TV,
    CAR
};

class DeviceWifiInfo {
public:
    DeviceWifiInfo();

    ~DeviceWifiInfo();

    DeviceClass GetDeviceClass();

    void UpdateDeviceCapability();

    void ResetWifiDeviceCfg();

    int GetVersion();

    void SetVerison(int version);

    bool GetCapsOfChooseP2pChannelOpt();

    void SetCapsOfChooseP2pChannelOpt(bool isEnabled);

    bool GetCapsOfDbdc();

    void SetCapsOfDbdc(bool isSupportDbdc);

    bool GetCapsOfCsa();

    void SetCapsOfCsa(bool isSupportCsa);

    bool GetCapsOfP2pRadarDetect();

    void SetCapsOfP2pRadarDetect(bool isP2pSupportRadarDetect);

    bool GetCapsOfP2pDfsChannel();

    void SetCapsOfP2pDfsChannel(bool isP2pSupportDfsChannel);

    bool GetCapsOfP2pIndoorChannel();

    void SetCapsOfP2pIndoorChannel(bool isP2pSupportIndoorChannel);

    void SetStaChannel(int channel);

    int GetStaChannel();

    bool GetApType();

    void SetApType(bool isPortalAp);

    std::string GetCurrentApSsid();

    void SetCurrentApSsid(const std::string& ssid);

    std::string GetCurrentApBssid();

    void SetCurrentApBssid(const std::string& bssid);

    void SetCurrentApHasInternet(bool hasInternet);

    bool GetCurrentApHasInternet();

    std::vector<int> GetP2pSupportChannel();

    void SetP2pSupportChannel(std::vector<int>& channels);

    std::string GetApPwd();

    void SetApPwd(const std::string& pwd);

    int GetApSecurityType();

    void SetApSecurityType(int securityType);

    int GetRouterType();

    std::string GenerateSessionId();

    std::string GetSessionId();

    /**
     * set SessionId of current cast service
     *
     * @param sessionId input sessionId generated by p2p go
     */
    void SetSessionId(std::string sessionId);

    /**
     * clear SessionId of current cast service
     */
    void ClearSessionId();

    void SetRouteType(int routerType);

    DeviceClass GetDeviceType();

    /**
     * set Go or Gc device type
     *
     * @param deviceType input Go or Gc device type
     */
    void SetDeviceType(DeviceClass deviceType);

    /**
     * get device config value from type
     *
     * @param type device wifi config type
     * @return the type value
     */
    int GetValueFromType(int type);

    /**
     * set device config info according type
     *
     * @param type device wifi config type
     * @param inputValue the value of type
     */
    void SetDeviceCfg(int type, int inputValue);

private:
    int m_version; // dual band adaptive concurrent
    bool m_isChooseP2pChannelOpt;
    bool m_isSupportDbdc;
    bool m_isSupportCsa;
    bool m_isP2pSupportRadarDetect;
    bool m_isP2pSupportDfsChannel;
    bool m_isP2pSupportIndoorChannel;
    bool m_isPortalAp;
    int m_staChannel;
    std::string m_currentApSsid;
    std::string m_currentApBssid;
    bool m_isCurrentApHasInternet;
    std::vector<int> m_P2pSupportChannelList;
    std::string m_pwd;
    std::string m_sessionId;
    int m_securityType;
    int m_routerType;
    DeviceClass m_deviceType;
};

class WifiHid2dCfg {
public:
    static WifiHid2dCfg& GetInstance();

    DeviceWifiInfo& GetSelfDeviceCfgInfo();

    DeviceWifiInfo& GetPeerDeviceCfgInfo();

    /**
     * get self device configuration in TLV format:type + length + value
     *
     * @param cfgType self wifi configuration type
     * @param cfgInfo configuration information
     * @param getDatValidLen configuration valid length
     */
    void GetSelfDeviceCfg(SelfCfgType cfgType, char cfgInfo[CFG_DATA_MAX_BYTES], int& getDatValidLen);

    /**
     * set peer wifi p2p config info
     *
     * @param cfgType self wifi configuration type
     * @param cfgData byte array
     * @param setDataValidLen the valid length of "cfgData"
     * @return 0: success, -1: fail
     */
    int Hid2dSetPeerWifiCfgInfo(PeerCfgType cfgType, char cfgInfo[CFG_DATA_MAX_BYTES], int setDataValidLen);

private:
    WifiHid2dCfg();

    ~WifiHid2dCfg();

    std::string ParseStringFromByteArray(char* data, int dataLen, int index, int maxLength);

    /** 2.4g channel count from channel 1 to channel 11 */
    void ParseP2pSupportChannelFromByteArray(char* data, int dataLen, int index, std::vector<int>& p2pSupportChannels);

    void HandlePeerApPassword();

    void HandleTlvData(int type, char* cfgData, int cfgDataLen, int index);

    int ParsePeerDeviceCfgInfo(PeerCfgType cfgType, char* cfgData, int cfgDataLen);

    int ParsePeerDeviceStaChanngeInfo(PeerCfgType cfgType, char* cfgData, int cfgDataLen);

    /**
     * find the value of index in byte array
     *
     * @param data byte array
     * @param value intput the value to find index
     * @return index in byte array
     */
    int FindIndexFromByteArray(char* data, int dataLen, int value);

    int SetBssidByte(int typeBssidValue, char* dataArray, int dataArrayLen, int offset);

    int SetP2pSupportChannelByte(char* dataArray, int dataArrayLen, int offset);

    int BuildTlvForIntVal(int type, int Value, char* tlvData, int tlvDataLen, int offset);

    int BuildTlvForStrVal(int type, std::string value, char* tlvData, int tlvDataLen, int offset);

    void HandlePeerStaStateChange(char* data, int dataLen, int index);

private:
    static DeviceWifiInfo m_selfDeviceInfo;
    static DeviceWifiInfo m_peerDeviceInfo;
};
}  // namespace Wifi
}  // namespace OHOS
#endif